<?php
/**
 * Created by PhpStorm.
 * User: wangjiangtao
 * Date: 2022/7/14
 * Time: 18:37
 */

namespace App\Modules\Popularize\Platform;


use App\Http\Model\AdvertiserCallbackLog;
use App\Http\Model\Device;
use App\Http\Model\Hint;
use App\Http\Model\MonitoringLink\AccessToken;
use App\Http\Model\MonitoringLink\HuaweiCallbackLogs;
use App\Http\Model\UserRegisterLog;
use App\Http\Services\AdvertiserCallbackLogServices;
use App\Http\Services\DeviceServices;
use Illuminate\Support\Facades\Redis;

class PlatformBaidu implements PlatformInterface {

    protected $callback;
    protected $platform;
    protected $device;
    protected $userId;

    protected $akey = 'NDU0MTg4NTM=';//baidu 的appkey
    protected $xxlAkey = 'NDU0OTU4OTQ=';//baidu 的appkey
    protected $redisPay = 'ADVERTISEMENT:BAIDU:PAY:%s'; //汇报记录，防止多次汇报
    const ACTIVITE_EVENT = 1;
    const REGISTER_EVENT = 2;
    const PAY_EVENT = 3;

    /**
     * 来来
     */
    const TARGET_TYPE_LL = 1;
    /**
     * 广告商
     */
    const TARGET_TYPE_ADS = 2;
    /**
     * 记录状态
     */
    const STATE_RECORD = 1;

    /**
     * 回调成功
     */
    const STATE_SUCCESS = 2;

    /**
     * 回调失败
     */
    const STATE_FAIL = 3;


    public function __construct($callback,$platform, $device, $userId)
    {
        $this->callback = $callback;
        $this->platform = $platform;
        $this->device = $device;
        $this->userId = $userId;
    }

    public function active():?bool
    {
        $requestData = $this->_buildRequestData(self::ACTIVITE_EVENT);
        if (empty($requestData)) {
            return false;
        }
        $params = json_decode(json_encode($this->device),true);
        $params = $this->_checkField($params);
        try {
            if (isset($this->device->guid) && $this->device->guid != ''){
                //查询是否存在设备信息，如果存在就说明设备已经激活
                $deviceModel = new Device();
                $deviceInfo = $deviceModel->getByGuid($this->device->guid);
                if(!empty($deviceInfo)){
                    write_log('BaiduAdvertiserService', 'platform', ["设备已存在", $params]);
                    return false;
                }
                $deviceModel->save($params);

                //获取用户注册并修改渠道
                $model = new UserRegisterLog();
                $userRegisterLog = $model->findRecordByGuid($this->device->guid, ['user_id']);
                if ($userRegisterLog && $this->platform != '' && is_numeric($userRegisterLog['platform']) && $userRegisterLog['platform'] == $userRegisterLog['channel_id']) {
                    $model->updatePlatform($userRegisterLog['user_id'], $this->platform);
                }
                write_log('BaiduAdvertiserService', 'platform', ["保存设备信息成功", $params]);
                return $this->_report(self::ACTIVITE_EVENT, $requestData);
            }

        } catch (\Exception $e) {
            write_log('BaiduAdvertiserService', 'platform', ["保存设备信息失败", $params,$e->getMessage()]);
            return false;
        }
        return true;
    }

    public function regist():?bool
    {
        $requestData = $this->_buildRequestData(self::REGISTER_EVENT);
        if (empty($requestData)) {
            return false;
        }
        return $this->_report(self::REGISTER_EVENT, $requestData);
    }

    public function pay($amount = 0):?bool
    {
        //只上报一次
        $key = sprintf($this->redisPay, $this->userId);
        $ret = Redis::set($key, 1, 'nx', 'ex', 86400 * 2);
        if (!$ret) {
            return false;
        }

        $requestData = $this->_buildRequestData(self::PAY_EVENT, $amount);
        if (empty($requestData)) {
            return false;
        }
        //校验注册天数
        $date = strtotime('+1 day',strtotime(date('Y-m-d',$this->device->created_at)));
        if (time() > $date){
            return false;
        }
        return $this->_report(self::PAY_EVENT, $requestData);
    }

    /**
     * 获取设备信息
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|void|null
     */
    public function getDevice(){
        return $this->device;
    }

    private function _buildRequestData($type, $payAmount = 0){
        $requestData = [];
        $requestData['action_time'] = time();
        $requestData['action_type'] = $type;

        //ios
        if (isset($this->device->idfa) && !empty($this->device->idfa)){
            $requestData['user_id']['idfa'] = strtolower($this->device->idfa);
            $requestData['user_id']['hash_idfa'] = md5($requestData['user_id']['idfa']);
        }
        //android
        if (isset($this->device->imei) && !empty($this->device->imei)){
            $requestData['user_id']['imei'] = strtolower($this->device->imei);
            $requestData['user_id']['hash_imei'] = md5($requestData['user_id']['imei']);
        }
        if (isset($this->device->oaid) && !empty($this->device->oaid)){
            $requestData['user_id']['oaid'] = strtolower($this->device->oaid);
            $requestData['user_id']['hash_oaid'] = md5($requestData['user_id']['oaid']);
        }

        if ($payAmount > 0) {
            $requestData['action_param']['value'] = $payAmount * 100; //分
        }
        return $requestData;
    }

    //上报磁力聚星服务器
    private function _report($type, $requestData){
        if (empty($requestData)) {
            return false;
        }
        $deviceId = '';
        if (isset($requestData['user_id']['hash_imei']) && $requestData['user_id']['hash_imei']){
            $deviceId = $requestData['user_id']['hash_imei'];
        }
        if (isset($requestData['user_id']['hash_idfa']) && $requestData['user_id']['hash_idfa']){
            $deviceId = $requestData['user_id']['hash_idfa'];
        }
        if (isset($requestData['user_id']['hash_oaid']) && $requestData['user_id']['hash_oaid']){
            $deviceId = $requestData['user_id']['hash_oaid'];
        }
        $insertId = (new AdvertiserCallbackLogServices())->insertData([
            'platform' => $this->platform??'',
            'device_md5_id' => $deviceId,
            'action_type' => $type,
            'target_type' => self::TARGET_TYPE_ADS,
            'state' => self::STATE_RECORD,
            'request_url' => $this->callback??'',
            'request_params' => json_encode($requestData),
        ]);
        try{
            $url = $this->callback;
            switch ($type){
                case self::ACTIVITE_EVENT:
                    $url = str_replace('{{ATYPE}}', 'activate', $url);
                    $url = str_replace('{{AVALUE}}', 0, $url);
                    break;
                case self::REGISTER_EVENT:
                    $url = str_replace('{{ATYPE}}', 'register', $url);
                    $url = str_replace('{{AVALUE}}', 0, $url);
                    break;
                case self::PAY_EVENT:
                    $url = str_replace('{{ATYPE}}', 'orders', $url);
                    $url = str_replace('{{AVALUE}}', $requestData['action_param']['value'], $url);
                    break;
            }
            //获取签名
            $url = $this->getSignUrl($url);

            $result = curlRequest($url, null, false, [], 3);
            write_log('BaiduAdvertiserService', 'platform', [$url, $requestData]);
            $dbStatus = (new AdvertiserCallbackLogServices())->updateByCondition(
                ['id' => $insertId],
                ['response_params' => json_encode($result),'state' => AdvertiserCallbackLog::STATE_SUCCESS]
            );
        }catch (\Exception $exception){
            $dbStatus = (new AdvertiserCallbackLogServices())->updateByCondition(['id' => $insertId], ['state' => AdvertiserCallbackLog::STATE_FAIL]);
            write_log('BaiduAdvertiserService', 'platform', [$url, $requestData, 'error_msg'=> $exception->getMessage(), 'db_status' => $dbStatus]);
            return false;
        }
        $result = json_decode($result);

        return isset($result->code) &&  $result->code == 0;
    }

    protected function _checkField($params = [])
    {
        do {
            $checkField = ['cid', 'aid', 'callback','advertiser_id', 'guid', 'idfa', 'version_no', 'os_name', 'device', 'channel_id', 'platform','imei','oaid','adid','conv_ext', 'client_ip'];
            if (empty($params)) {
                break;
            }

            $inputParams = [];
            foreach ($checkField as $field) {
                if (array_key_exists($field, $params)) {
                    $inputParams[$field] = $params[$field];
                }
            }

            $params = $inputParams;
        } while (false);

        return $params;
    }

    public function getSignUrl($url){
        $akey = $this->getAkey();
        $url = explode('&sign=',$url)[0];
        $val = $url.$akey;
        $sign = md5($val);
        return $url.'&sign='.$sign;
    }

    public function getAkey(){
        if ($this->platform && strstr($this->platform ,'xxl')){
            $akey = $this->xxlAkey;
        }
        return $akey??$this->akey;
    }
}
